Fork me on GitHub
ElasticSearch Nosql

把 ElasticSearch 当成是 NoSQL 数据库

Elasticsearch 可以被当成一个 "NoSQL"-数据库来使用么? NoSQL 意味着在不同的环境下存在不同的东西, 而erestingly 它并不是真的跟 SQL 有啥关系. 我们开始只会觉得 "可能"而已, 所以细细研究了 Elasticsearch 的各种属性,包括它已经为了成就最具灵活性,可伸缩性和性能优异的分析查询引擎的那些属性.

NoSQL 数据库是什么?

NoSQL-数据库 将 NoSQL 定义为“下一代主要解决如下问题的数据库: 非关系型的,分布式的,开元的并且可以扁平扩展.”. 换言之,它并不是一个精确的定义.

它尤其与SQL无关. 比方说, Hive 查询语言的灵感显然来自 SQL.  Esper查询语言同样如此, 只是它操作的是流而不是关系. 还有你知道 PostgreSQL 过去被命名为 “Postgres” 并使用 “Quel” 作为它的查询语言么? 而首先作为一个关系型数据库管理系统( ORDBMS), 它现在同样有许多的特性使其具备无模式文档存储的能力.

它同样也和ACID-特性无关. Hyperdex 就是一个 NoSQL-数据库的例子,它的目标就是提供 ACID-事务能力. MySQL, 确实是一个 SQL-数据库, 历史上它有一段解释 ACID 的真正意义的暧昧时期.

关系型的? 虽然大多数的 NoSQL-数据库并不支持加入传统关系型数据意义相同的功能,但还是有一些那样做了,并将其留给用户当做练习使用. RethinkDBHive 还有 Pig, 等等. Neo4j, 面向图形的数据库, 确实是处理关系用的 - 它擅于遍历图中的关系 (比如,图中的边) . Elasticsearch 有一个概念叫做加入父子关系的“查询时间”和加入嵌套类型的“索引时间“.

分布式的? 已经有一些分布式的 SQL-数据库 了, 并以 一些项目 旨在做一些像一个NoSQLite那样的事情, 更新一代的数据库趋向于在某些方式上具备分布式能力.

总而言之, 既没有道理给 NoSQL 做出精确的定义, 也不能简单的说 Elasticsearch 是一个“文档存储”-类型的NoSQL-数据库. 在我写这篇文章的时候, nosql-database.org 列出了超过20 个那样的东西.

在下一节,我们将关注一些重要的属性并且看看 Elasticsearch 为什么要实现或者不去实现它们.

无事务

Lucene, 是 Elasticsearch 的构建的基础, 它是由一个事务的概念的. 而Elasticsearch在另外的方面, 并没有典型意义的事务. 对于已经提交的文档并没有办法回滚, 而你也不能提交一组文档并且为它们所有或者其中一些建立索引. 然而它所具备的, 是一个用来确保业务过程持久性而不用做昂贵的Lucene提交的预写日志. 你也可以指定索引操作的一致性级别, 以确保在返回之前有多少副本可以拿来确认操作条件. 默认的是法定人数, 例如 ⌊n2⌋

在逐个切片进行处理的方式中,当一个索引被刷新时,默认是一秒钟一次,就需要对变更的可见性进行控制。

通过制定提交文档的版本,可以进行乐观并发控制。

Elasticsearch追求的是速度。支持分布式事务是一大块工作。不支持分布式事务会使得很多事情变得容易起来。只要我们能接受读取到的数据有些陈旧,而且所有人看到的是同一时间点的数据,那么Elasticsearch就可以利用缓存提供很多服务 - 这对于我们钟爱的极速性能来说是至关重要的。

模式灵活

Elasticsearch 不要求你先指定模式。扔给它一个 JSON 文档,它就会进行一些训练有素的猜测来推断其类型。对于数值、布尔、时间戳它可以做的很好。对于字符串,它会使用“标准化”的分析,这通常是良好的开始。

它是有商榷的“无模式”,在这个意义上你不必指定一个模式,我们更愿意把它认做是“模式灵活”。为了开发大规模的搜索、分析,你确实需要对模式进行微调。Elasticsearch 有大量的强大工具可以帮助你,例如动态模板、多字段对象等。这在我们关于映射的文章里会谈及更多。

关系和约束

Elasticsearch是一种面向文档的数据库。你想要对之进行搜索的整个对象关系图,都需要进行索引,在对文档进行索引之前,它们必须先被反规范化。反规范化提升了查询性能(因为不再需要进行关联查询),使用了更多存储空间(因为数据必须被存储多次),但是,要保持数据一致性和实时性则更加困难(因为任何数据改变都必须被写入到所有实例中去)。不过,对于一次写入频繁读取的工作场景,它的表现相当优异。

举例来说,假设你在数据库中存储了客户、订单和产品等数据,现在你想要通过产品名字和客户姓名来查找订单。可以这样来解决这个问题:在对订单进行索引时,把客户和产品的所有必要信息都加进来。这样的话,查询就非常简单,但是当你想要改变某个产品的名字时会出现什么情况呢? 在进行了良好规范化的关系型模型中,你只需要修改该产品对应的单条记录就搞定了。这是关系型数据库所擅长的。而在反规范化的文档数据库中,将不得不更新与该产品有关的所有订单。

换句话说,在面向文档类型的数据库中,比如Elasticsearch, 我们对文档进行映射和存储设计只是为了优化查询和信息获取的性能。

在介绍中已经提到,Elasticsearch中可以使用父/子-关系进行“查询时”连结,也可以使用内嵌类型进行“索引时”连结。我们会在以后的文章中对该主题进行深入介绍。我们推荐Martijn van Groningen的一篇文章“Document relations with Elasticsearch”.

大多数关系型数据库也会允许你指定约束关系,来定义什么需要保持一致性,什么不需要保持一致性。比如,参照完整性和唯一性都是强制性的。你可以要求账户变更金额必须是正数,等等。而面向文档的数据库不倾向于这么做,Elasticsearch就是如此。

鲁棒性

一个数据库应当是鲁棒的,尤其是当它是你权威的记录系统时。理想情况下,一个耗费资源的查询应当可以被撤销,你肯定不希望数据库停止工作,除非你命令它停下来。

不幸的是,Elasticsearch (以及它的组件)目前并没有很好的处理OutOfMemory错误。我们在Elasticsearch in Production, OutOfMemory-Caused Crashes一文中进行了更加深入的讨论。所以,给Elasticsearch配置足够多的内存就显得非常重要,而且在生产集群中要谨慎运行那些无法预知将会耗费多少内存的查询。

不过,随着Elasticsearch越来越成熟,这个问题很可能会得到改善,记住Elasticsearch的目标是追求速度,所以它假设内存永远是充足的。

分布式

另请参考: Elasticsearch in Production, Networking.

Shay Banon在创建Elasticsearch之前,在Compass工作过。由于意识到它很难转变成一个分布式的搜索引擎,他就从头开始创建了Elasticsearch1。 Elasticsearch被设计成分布式的且易于扩展,用来在商用硬件上处理海量数据。

作为一个分布式的系统,Elasticsearch的上手和使用都令人难以置信的简单,但是分布式系统本身是很复杂的。关于这一点,我们在Elasticsearch in Production, Networking有更多讨论,所以下面只是一个简短的摘要。

分布式系统天生的特性,意味着很多事情都可能会出错。同样的,不同的数据库系统致力于拥有不同强项: 有些力争强大的安全保证,另外一些则致力于高可用性,即使某些时候(甚至多数时候)出现错误也在所不惜。而且,正如Kyle Kingsbury在他杰出的网络分区的风险系列文章中所指出的那样,当问题发生时,实际上数据库系统并没有像它们所宣称的那样来处理问题。简言之,他发现当分布式数据库运行良好晴空万里时,绝大部分数据库在遭受到大量可能的问题时所做的努力,都会以失败而告终。

在一致性,可用性,以及分区容错性方面,Elasticsearch 是一个CP系统,一个相当不靠谱的“一致性”定义。如果你有一个只读的工作负载, Elasticsearch 允许你通过不严格的“最小主节点”要求(如不需要quorum)实现AP行为。然而,通常你需要集群中大量节点是可用的。写入一个配置错误的没有大量节点的集群,像“split brain”集群,可能引起无法恢复的数据丢失。这不只是特定于Elasticsearch的。

Elasticsearch 选择自己的主节点。然而这是一个相当简单但不是非常可靠的算法,这在现实世界的网络压力下可能导致很多问题。事实上,我们管理成百上千的集群,经常看到主节点选择问题,因此我们主动将主节点移入ZooKeeper, 当然我们也有其他目的。

在拓展性方面,索引被分到了一个或多个碎片中。这在索引创建时就指定了并且不能改变。因此,随着预期的增长,一个索引应该被合理的分割。随着越来越多的节点添加到Elasticsearch集群中来,它在重新分配和移动碎片上表现良好。因此,Elasticsearch很容易拓展。

安全

另请参阅: Elasticsearch in Production, Security.

Elasticsearch没有提供授权和认证特性。你可以认为,任何人只要能连接到你的Elasticsearch集群,就拥有了“超级用户”权限,尤其是当Elasticsearch的强大脚本功能被激活时。

总结

如果本文描述的这些限制都不能阻止你,你当然可以使用Elasticsearch作为主存储库。一个不错的例子是,当你使用Logstash时。Logstash是一个神奇的工具,用来管理日志并把它们导入到Elasticsearch中,你可以只是对日志进行备份以防万一。日志都是一次写入,多次读取的。不需要升级,不需要事务支持,没有完整性约束,等等。

那么像Postgres那样的系统怎么样呢,它有全文检索和ACID-事务。 (其它例子包括MySQL, MongoDB, Riak等等的全文检索能力) 你当然可以通过Postgres来实现基本的检索,但是在性能上和功能上与ElasticSearch都有巨大的差距。正如我们在事务那一节中所提到的,Elasticsearch会做很多缓存,所以有可能会“欺骗”我们,而且不关心多版本之间的并发控制以及其它复杂的事情。搜索远不止在一段文本中找到一个关键字那么简单:它是利用领域特定知识来实现良好的相关度模型,由此给出整个结果空间的一个全貌,并且能做拼写检查和自动补全之类的工作。而且所有这些工作都要保证速度。

Elasticsearch通常被用作其它数据库的补充。那样的数据库系统要有强大的数据约束保证、容错性和鲁棒性、高可用性和带事务支持的数据更新能力,它维护着核心数据 - 这些数据随后会被异步推送到Elasticsearch中去(也可能是抽取,前提是你使用了Elasticsearch的某一种“rivers”)。 保持数据同步是我们打算将来撰文深入探讨的话题。这里,在Found网站的文章中,我们使用具有代表性的PostgreSQL和ZooKeeper来提供源数据,并把这些数据输入给Elasticsearch来提供强大的搜索。

像其它所有事情一样,没有包治百病的灵丹妙药,没有一个数据库可以做到所有的事情。也许这种情况会永远持续下去,所以一定要了解你的数据库的优点和弱点!

参考资料

Banon, Shay: The Future of Compass & ElasticSearch – http://www.kimchy.org/the_future_of_compass/

 

posted on 2016-11-18 10:56  HackerVirus  阅读(595)  评论(0编辑  收藏  举报